07. Mockito
Mockito
ND079 JPND C3 L5 A05a Introduction To Mockito V3
Why Write our Own Mocks?
Mockito is a framework that can automatically generate mock objects. Mockito uses slightly different definitions for Mock
and Spy
than we saw earlier:
A Mockito Mock is an object that can programmatically implement any behavior from any of the test doubles we learned earlier. Mockito Mocks can be spies, dummies, stubs, or mocks.
A Mockito Spy can do everything a Mock can do, but it also inherits the behavior of the class it extends. Sometimes this construct is referred to as a partial mock, because it's part mock, part original class.
Mock vs. Spy
Generally, you should only use Mockito Mock
. Creating partial mocks is dangerous, because they allow you to override the behavior of the same class you're testing. At best, that means your class is poorly designed, and at worst, it means you've created a unit test that always passes because it defines the very behavior it is testing.
The only reason I've encountered to use Spies is if you need to verify that internal methods are called on your tested class. This usually is evidence of some design problems, but can be unavoidable on some legacy code.
ND079 JPND C3 L5 A05b Demo Mockito
Adding Mockito
First, add the dependency to Maven. Updated dependency information available at https://site.mockito.org
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>3.6.0</version>
<scope>test</scope>
</dependency>
Next, attach the Mockito test runner to your unit test by using the @ExtendsWith
annotation from JUnit 5.
@ExtendWith(MockitoExtension.class)
public class UserServiceMockitoTest {
}
Creating a Mock
Creating a mock in Mockito is as simple as annotating a class attribute with the @Mock
annotation. For example, I could create a Mock SalesService
using this approach. The code below automatically creates a @Mock SalesService
for every unit test and injects it into a new UserService
in the init method.
@ExtendWith(MockitoExtension.class)
public class UserServiceMockitoTest {
private UserService userService;
@Mock
private SalesService salesService;
@BeforeEach
void init() {
userService = new UserServiceImpl(salesService);
}
}
You can also inject the Mock into UserService
automatically using the @InjectMocks
annotation instead of using a @BeforeEach
method.
Writing a Unit Test with Mockito
Our previous test with the FakeSalesService
created a fake using the desired value it should return.
@ParameterizedTest
@ValueSource(strings={"Fizz", "Buzz", "FizzBuzz"})
public void fancyBusiness_getsFizzBuzzString_returnsSameString(String returnString) {
SalesService salesService = new FakeSalesService(returnString);
UserService userService = new UserServiceImpl(salesService);
//which number we pass doesn't matter, because we're controlling the return value of FizzBuzz
assertEquals(returnString, userService.fancyBusiness(1));
}
This same behavior can be emulated by using Mockito using the when
method. The below method specifies that when salesService.fizzBuzz
is called with a value of 1, then return the value input.
@ParameterizedTest
@ValueSource(strings={"Fizz", "Buzz", "FizzBuzz"})
public void fancyBusiness_getsFizzBuzzString_returnsSameString(String input) {
Mockito.when(salesService.fizzBuzz(1)).thenReturn(input);
Assertions.assertEquals(input, userService.fancyBusiness(1));
}